﻿/* Copyright 2008-10 Jarrett Vance
 * see http://www.codeplex.com/blogsvc/license */
namespace AtomSite.WebCore
{
  using AtomSite.Domain;
  using System.Collections.Generic;
  using System;
  using System.Linq;
  using StructureMap;
  using System.Web.Mvc;

  public class PageModel : BaseModel
  {
    public PageModel() : base()
    {
      PageWidth = "doc1";
      PageTemplate = "yui-t5";
      PageName = string.Empty;
      AssetGroups = new List<string>();
      Assets = new List<Asset>();
      TailScript = string.Empty;
    }
    
    public string PageName { get; protected set; }
    public ICollection<string> AssetGroups { get; protected set; }
    public ICollection<Asset> Assets { get; protected set; }
    public string PageWidth { get; protected set; }
    public string PageTemplate { get; protected set; }

    public string TailScript { get; protected set; }

    public void AddToTailScript(string script)
    {
      //if (TailScript == null) TailScript = string.Empty;
      TailScript += Environment.NewLine + script;
    }
  
    /// <summary>
    /// Gets the name of the aspx page (without .aspx extension) when using Web Forms view engine
    /// to update model with dependencies and other configuration. Also sets the asset groups this
    /// page requires.
    /// </summary>
    /// <param name="page"></param>
    /// <param name="assetGroups"></param>
    /// <returns></returns>
    public void UpdatePageModel(System.Web.UI.Page page, string[] assetGroups)
    {
        OnUpdatePageModel(page, assetGroups);
    }

    protected virtual void OnUpdatePageModel(System.Web.UI.Page page, string[] assetGroups)
    {
        //TODO: determine asset groups based on collection configuration

        AssetGroups = AssetGroups.Concat(assetGroups).ToList();

        string virpath = page.AppRelativeVirtualPath;
        int start = page.AppRelativeVirtualPath.LastIndexOf('/') == -1 ? 0 :
        page.AppRelativeVirtualPath.LastIndexOf('/') + 1;
        int length = page.AppRelativeVirtualPath.LastIndexOf(".aspx") - start;
        PageName = page.AppRelativeVirtualPath.Substring(start, length);

        //using the page name, find width and template using scope fallback rules
        var pages = Service.GetServicePages(Scope, assetGroups, PageName);

        var pageWidth = pages.Where(p => p.Width != null).LastOrDefault();
        if (pageWidth != null) PageWidth = pageWidth.Width;
        var pageTemplate = pages.Where(p => p.Template != null).LastOrDefault();
        if (pageTemplate != null) PageTemplate = pageTemplate.Template;

        IContainer container = (IContainer)page.Application["Container"];

        //global
        IAssetService assetSvc = container.GetInstance<IAssetService>();
        assetSvc.UpdatePageModel(this);

        //page
        {
            IPage p = container.TryGetInstance<IPage>(PageName);
            if (p != null) p.UpdatePageModel(this);
        }

        var includes = Service.GetIncludes(Scope, assetGroups, PageName);

        //TODO: should be part of each model but can't get it to work with current PageModel
        //also allow inline widgets to update pagemodel
        //if (this is EntryModel)
        //{
        //    includes = includes.Concat(((EntryModel)this).Entry.Xml.Elements(Include.IncludeXName).Select(i => new Include(i)));
        //}

        //let each widget update page model
        foreach (Include include in includes)
        {
            var w = container.TryGetInstance<IWidget>(include.Name);
            if (w != null) w.UpdatePageModel(this, include);
        }
    }


    /// <summary>
    /// Gets the name of the aspx page (without .aspx extension) when using Web Forms view engine
    /// to update model with dependencies and other configuration.
    /// </summary>
    /// <param name="page"></param>
    /// <returns></returns>
    public virtual void UpdatePageModel(System.Web.UI.Page page)
    {
        OnUpdatePageModel(page, new string[] { Asset.DefaultGroup });
    }
  
  }

  public class ErrorModel : PageModel
  {
    public ErrorModel() { }
    public ErrorModel(Exception ex)
    {
      HandleErrorInfo = new HandleErrorInfo(ex, null, null);
    }
    public HandleErrorInfo HandleErrorInfo { get; set; }
  }
}
